package cn.itsource.ymcc.service.impl;

import cn.itsource.ymcc.constant.ErrorConstantCode;
import cn.itsource.ymcc.constant.MQConstants;
import cn.itsource.ymcc.constant.RedisConstants;
import cn.itsource.ymcc.domain.CourseOrder;
import cn.itsource.ymcc.domain.CourseOrderItem;
import cn.itsource.ymcc.dto.PlaceOrderDTO;
import cn.itsource.ymcc.feignclient.CourseFeignClient;
import cn.itsource.ymcc.mapper.CourseOrderMapper;
import cn.itsource.ymcc.result.JSONResult;
import cn.itsource.ymcc.service.ICourseOrderItemService;
import cn.itsource.ymcc.service.ICourseOrderService;
import cn.itsource.ymcc.util.AssertUtil;
import cn.itsource.ymcc.util.CodeGenerateUtils;
import cn.itsource.ymcc.util.SecurityContextUtil;
import cn.itsource.ymcc.vo.CourseDetailVO;
import cn.itsource.ymcc.vo.CourseOrderDetailVo;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.json.Json;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author gwk
 * @since 2023-03-12
 */
@Service
public class CourseOrderServiceImpl extends ServiceImpl<CourseOrderMapper, CourseOrder> implements ICourseOrderService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private RocketMQTemplate mqTemplate;

    @Autowired
    private CourseFeignClient courseFeignClient;

    @Autowired
    private ICourseOrderItemService itemService;

    @Override
    public String placeOrder(PlaceOrderDTO placeOrderDTO) {
        // 1. 参数校验通过JS303实现
        List<String> courseIds = placeOrderDTO.getCourseIds();
        Integer payType = placeOrderDTO.getPayType();
        String token = placeOrderDTO.getToken();

//      2. 校验token,
//      // key -- userid:courseids        value --- token(uuid)
        Long loginID = SecurityContextUtil.getUserDetail().getUserId();
        String strIds = courseIds.stream().collect(Collectors.joining(","));
        String key = String.format(RedisConstants.ORDER_TOKEN_KEY,loginID,strIds);
        Object obj = redisTemplate.opsForValue().get(key);
        AssertUtil.isNotNull(obj, ErrorConstantCode.TOKEN_ERROR_60010);
        AssertUtil.isTrue(token.equals((String)obj),ErrorConstantCode.TOKEN_ERROR_60010);

//       查询订单信息  courseids
        JSONResult orderDetail = courseFeignClient.getOrderDetail(strIds);
        AssertUtil.isTrue(orderDetail.isSuccess(),ErrorConstantCode.COURSE_ERROR_30010);
        CourseOrderDetailVo courseOrderDetailVo =  JSON.parseObject(JSON.toJSONString(orderDetail.getData()), CourseOrderDetailVo.class);

        CourseOrder courseOrder = new CourseOrder();
        Date date = new Date();
        courseOrder.setCreateTime(date);
        courseOrder.setOrderNo(CodeGenerateUtils.generateUnionPaySn());
        courseOrder.setTotalAmount(courseOrderDetailVo.getTotalAmount());
        courseOrder.setTotalCount(courseIds.size());
        courseOrder.setStatusOrder(CourseOrder.NO_PAY);
        courseOrder.setUserId(loginID);
        StringBuffer sb = new StringBuffer();
        courseOrderDetailVo.getCourseInfos().forEach(courseDetailVO -> {
            sb.append(courseDetailVO.getCourse().getName()).append(",");
            });
        String titile = String.format("购买课程 [%s] , 支付[%s] 元",sb.toString(),courseOrderDetailVo.getTotalAmount());
        courseOrder.setTitle(titile);
        courseOrder.setPayType(payType);

       // insert(courseOrder);

//     查询课程信息 -- 》 封装的订单信息对象 --》 数据库
        for (CourseDetailVO courseInfo : courseOrderDetailVo.getCourseInfos()) {
            CourseOrderItem item = new CourseOrderItem();
            //item.setOrderId(courseOrder.getId());//没有保存，就没有订单id
            item.setAmount(courseInfo.getCourseMarket().getPrice());
            item.setCount(1);
            item.setCreateTime(date);
            item.setCourseId(courseInfo.getCourse().getId());
            item.setCourseName(courseInfo.getCourse().getName());
            item.setCoursePic(courseInfo.getCourse().getPic());
            item.setOrderNo(courseOrder.getOrderNo());

            courseOrder.getCourseOrderItems().add(item);
            //itemService.insert(item);
        }

        //发送MQ的事务消息，并在接收到MQ的确认回调之后在保存 courseOrder 和 CourseOrderItem
        // String txProducerGroup, 生成者组
        // String destination, topic:tags
        // Message<?> message, 消息体
        // Object arg 格外的参数，帮我们跟方便的执行本地事务。
        String jsonString = JSON.toJSONString(courseOrder);
        Message<String> build = MessageBuilder.withPayload(jsonString).build();
        mqTemplate.sendMessageInTransaction(MQConstants.TX_COURSER_ORDER_PRODUCE_GROUP,
                "order-topic:courser-ordre-tags",
                 build
                ,courseOrder
                );

        // 	删除 redis的token
        redisTemplate.delete(key);

        return courseOrder.getOrderNo();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void saveOrderAndItem(CourseOrder courseOrder) {
            // 保存订单
            insert(courseOrder);

            // 保存订单项
            for (CourseOrderItem courseOrderItem : courseOrder.getCourseOrderItems()) {
                courseOrderItem.setOrderId(courseOrder.getId());
                itemService.insert(courseOrderItem);
            }
    }
}
